package com.hs.egova.exception;

import com.hs.egova.base.ResultInfo;
import com.hs.egova.tool.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindingResult;
import org.springframework.validation.ObjectError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author husheng
 * @version v1.0
 * @date 2021/7/27 17:21
 * @email husheng@egova.com.cn
 */
@Slf4j
@RestControllerAdvice("")
public class GlobalExceptionHandler {

    /**
     * 缺少参数异常
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(MissingServletRequestParameterException.class)
    public ResultInfo parameterMissingExceptionHandler(MissingServletRequestParameterException e) {
        log.error(" ", e);
        return new ResultInfo(false, "请求参数" + e.getParameterName() + "不能为空");
    }

    /**
     * 参数校验异常处理器
     * @param e
     * @return
     */
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(HttpMessageNotReadableException.class)
    public ResultInfo parameterBodyMissingException(HttpMessageNotReadableException e) {
        log.error("", e);
        return new ResultInfo(false, "参数体不能为空");
    }


    /**
     * 参数校验
     * @param e
     * @return
     */
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResultInfo parameterException(MethodArgumentNotValidException e) {
        log.error("", e);
        BindingResult exceptions = e.getBindingResult();

        if (exceptions.hasErrors()) {
            List<ObjectError> errorList = exceptions.getAllErrors();
            if (!errorList.isEmpty()) {
                StringBuilder sb = new StringBuilder("");
                for(ObjectError error : errorList) {
                    sb.append(error.getDefaultMessage()+" ");
                }
                //errorList.stream().map(ObjectError::getDefaultMessage).collect(Collectors.toList())
                //errorList.forEach(ex -> sb.append(ex.getDefaultMessage()));
                return new ResultInfo(false, sb.toString());
            }
        }
        return new ResultInfo(false, "参数错误");
    }

    /**
     * 表单形式的参数校验，配合@Validated使用
     * @param e
     * @return
     */
    @ExceptionHandler(ConstraintViolationException.class)
    public ResultInfo constraintViolationException(ConstraintViolationException e) {
        log.info("ConstrainViolationException", e);
        Set<ConstraintViolation<?>> cves = e.getConstraintViolations();
        StringBuilder errorMsg = new StringBuilder();
        cves.forEach(ex -> errorMsg.append(ex.getMessage()));
        ResultInfo resultInfo = new ResultInfo(false, errorMsg.toString());
        return resultInfo;
    }

    @ResponseStatus(HttpStatus.BAD_REQUEST)
    @ExceptionHandler(ParamErrorException.class)
    public ResultInfo paramExceptionHandler(ParamErrorException e) {
        log.error(" ", e);
        if (!StringUtils.isEmpty(e.getMessage())) {
            return new ResultInfo(false, e.getMessage());
        }
        return new ResultInfo(false, "参数错误");
    }

    @ExceptionHandler(Exception.class)
    public ResultInfo commonException(Exception e) {
        log.error(e.getMessage(), e);
        return new ResultInfo(false, "操作错误");
    }

    /**
     * 公共代码公共异常抛出
     * @param egovaCommonException
     * @return
     */
    @ExceptionHandler(EgovaCommonException.class)
    public ResultInfo egovaException(EgovaCommonException egovaCommonException) {
        log.error(egovaCommonException.getMessage());
        return new ResultInfo(false, egovaCommonException.getMessage());
    }
}
